﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using DesignerHelper.EventHandlers;
using DesignerHelper.Help;
using DesignerHelper.Main;
using SpreadsheetGear;
using WorkbookDesigner.Main;
using SGForm = SpreadsheetGear.Windows.Forms;

namespace WorkbookDesigner.UI
{
    public partial class FindReplaceDialog : Form
    {
        private static FindReplaceDialog _frd = null;

        //窗口初始化函数
        private FindReplaceDialog()
        {
            InitializeComponent();
        }

        private FindReplaceDialog(IMainWindow mw, OperationType ot) : this()
        {
            Mw = mw;
            RefreshWbv();
            tabControl1.SelectedTab = ot == OperationType.Replace ? tabPageReplace : tabPageFind;
            switch (ot)
            {
                case OperationType.Find:
                    tabPageFind.Select();
                    break;

                case OperationType.Replace:
                    tabPageReplace.Select();
                    break;
            }


            CheckTabPageControl();
            AddEventHandler();

        }

        internal enum OperationType
        {
            Find, Replace
        }

        private SGForm.WorkbookView ActiveView { get; set; }
        private bool AutoSizeListRangesOnCacheVirtualItems { get; set; }
        private FindAll findAll { get; set; }
        private IMainWindow Mw { get; set; }

        internal static void ShowForm(IMainWindow mw, OperationType ot)
        {
            if (mw?.ActiveBookForm != null)
            {
                if (_frd == null)
                {
                    _frd = new FindReplaceDialog(mw, ot);
                    _frd.Show(mw.GetForm());
                }
                else
                    _frd.Activate();
            }
            else
                MesBox.ErrorMessage("Could not open FindAndReplaceDialog");
        }

        #region 事件处理

        private void _disableDialog()
        {
            buttonFineNext.Enabled = false;
            buttonFindAll.Enabled = false;
            buttonReplace.Enabled = false;
            buttonReplaceAll.Enabled = false;
            ResultListView.Enabled = false;
        }

        private void _enableDialog()
        {
            buttonFineNext.Enabled = true;
            buttonFindAll.Enabled = true;
            buttonReplace.Enabled = true;
            buttonReplaceAll.Enabled = true;
            ResultListView.Enabled = true;
        }

        private void AddEventHandler()
        {
            Mw.FileOperator.DisableUI += disableDialog;
            Mw.FileOperator.EnableUI += enableDialog;
            Mw.FileOperator.CellBeginEditInternal += disableDialog;
            Mw.FileOperator.CellCancelEditInternal += enableDialog;
            Mw.FileOperator.CellEndEditInternal += enableDialog;
            Mw.FileOperator.BookSetModified += TestRefresh;

        }


        private void disableDialog(object sender, EventArgs e)
        {
            _disableDialog();

            if (e is NoFormLeftEventArgs)
            {
                VirtualListSize = 0;//设为0则不再自动获取Item
                ResultListView.Items.Clear();
                ActiveView = null;
            }
        }

        private void enableDialog(object sender, EventArgs e)
        {
            if (e is SGForm.CellCancelEditEventArgs || e is SGForm.CellEndEditEventArgs || e is FormExistEventArgs)
            {
                _enableDialog();
                //RefreshWbv();

            }
        }

        private void RemoveEventHandler()
        {
            Mw.FileOperator.DisableUI -= disableDialog;
            Mw.FileOperator.EnableUI -= enableDialog;
            Mw.FileOperator.CellBeginEditInternal -= disableDialog;
            Mw.FileOperator.CellCancelEditInternal -= enableDialog;
            Mw.FileOperator.CellEndEditInternal -= enableDialog;
            Mw.FileOperator.BookSetModified -= TestRefresh;
        }


        #endregion 事件处理

        #region 刷新本地workbookview变量

        private bool RefreshSuccessed()
        {
            RefreshWbv();
            return ActiveView != null;
        }

        private void RefreshWbv()
        {
            ActiveView = Mw.ActiveView;
            //VirtualListSize = 0;
        }

        private void TestRefresh(object sender, BookSetEventArgs e)
        {
            VirtualListSize = 0;
            ResetResultLabel();
            ResultListView.Items.Clear();
            RefreshSuccessed();
        }
        #endregion 刷新本地workbookview变量

        #region 控件相关

        private enum Within
        {
            Sheet, Workbook, WorkbookSet
        }

        private bool Loopthrough => !checkBoxLoopThrough.Checked;

        private string ReplaceText
        {
            get
            {
                return comboBoxReplace.Text;
            }
        }

        //////////////////////////////////////////
        private string SearchText
        {
            get
            {
                return comboBoxFind.Text;
            }
        }

        private bool SelectedCaseSensitive
        {
            //区分大小写
            get
            {
                return checkBoxCaseSensitive.Checked;
            }
        }

        private LookAt SelectedLookAt
        {
            //完全匹配|部分匹配
            get
            {
                return checkBoxEntireCells.Checked ? LookAt.Whole : LookAt.Part;
            }
        }

        private FindLookIn SelectedLookIn
        {
            //查找内容,数值/公式
            get
            {
                switch (comboBoxLookIn.SelectedIndex)
                {
                    case 0:
                        return FindLookIn.Formulas;

                    case 1:
                        return FindLookIn.Values;
                }
                return FindLookIn.Formulas;
            }
        }

        private SearchOrder SelectedSearchOrder
        {
            //查找方式,行/列
            get
            {
                switch (comboBoxSearch.SelectedIndex)
                {
                    case 0:
                        return SearchOrder.ByRows;

                    case 1:
                        return SearchOrder.ByColumns;
                }
                return SearchOrder.ByRows;
            }
        }

        private Within SelectedWithin
        {
            get
            {
                switch (comboBoxWithin.SelectedIndex)
                {
                    case 0:
                        return Within.Sheet;

                    case 1:
                        return Within.Workbook;

                    case 2:
                        return Within.WorkbookSet;
                }
                return Within.Sheet;
            }
        }

        private int VirtualListSize
        {
            get
            {
                return ResultListView.VirtualListSize;
            }
            set
            {
                ResultListView.BeginUpdate();
                ResultListView.VirtualListSize = value;
                ResultListView.EndUpdate();
            }
        }

        private static string GetResultText(int count, OperationType ot)
        {
            switch (ot)
            {
                case OperationType.Find:
                    return "共发现 " + count + " 处结果";
                case OperationType.Replace:
                    return "共完成 " + count + " 处替换";
                default:
                    return string.Empty;
            }
        }

        private void ResetResultLabel()
        {
            resultStatusLabel.Text = "";
            resultStatusLabel.ForeColor = System.Drawing.Color.Transparent;
        }

        private void SetFormOpacity(bool formActivated)
        {
            Opacity = checkBoxChangeOpacity.Checked &&
                       ((!formActivated && radioOpaLostFocus.Checked) || radioOpaAlways.Checked)
                ? Math.Round(Convert.ToDouble(trackBarChangeOpactiy.Value) / 100, 2)
                : 1.00;
        }
        private void SetResultLabel(string text)
        {
            resultStatusLabel.Text = text;
            resultStatusLabel.ForeColor = System.Drawing.Color.Red;
        }

        #endregion 控件相关

        #region About Range

        private static IRange GetAfterRange(IRange range)
        {
            //查找将从afterRange之后的单元格开始
            //该方法获取查找区域的最后一个单元格(向下查找时,最右最下)
            return range[range.RowCount - 1, range.ColumnCount - 1];
        }

        private bool AddAllRanges(List<IRange> list, IWorkbookSet workbookSet, bool checkLocked)
        {
            if (RefreshSuccessed())
            {
                IWorkbooks workbooks = workbookSet.Workbooks;
                for (int i = 0; i < workbooks.Count; i++)
                {
                    if (!AddAllSheetRanges(list, workbooks[i], checkLocked))
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        private bool AddAllRanges(List<IRange> list, IWorkbook workbook, bool checkLocked)
        {
            if (workbook.Worksheets.Count > 1)
            {
                return AddAllSheetRanges(list, workbook, checkLocked);
            }
            return true;
        }

        private bool AddAllSheetRanges(List<IRange> list, IWorkbook workbook, bool checkLocked)
        {
            IWorksheets worksheets = workbook.Worksheets;
            for (int i = 0; i < worksheets.Count; i++)
            {
                IWorksheet worksheet = worksheets[i];
                if ((worksheet.Visible == SheetVisibility.Visible) && !AddRange(list, worksheet.Cells, checkLocked))
                {
                    return false;
                }
            }
            return true;
        }

        private bool AddRange(List<IRange> list, IRange range, bool checkLocked)
        {
            if ((checkLocked && range.Worksheet.ProtectContents) && (range.Locked || !range.LockedDefined))
            {
                return false;
            }
            list.Add(range);
            return true;
        }

        private void AutoSizeRangeList(int startIndex, int endIndex)
        {
            ActiveView.GetLock();
            ResultListView.BeginUpdate();
            try
            {
                using (Graphics graphics = CreateGraphics())
                {
                    ListView.ColumnHeaderCollection columns = ResultListView.Columns;
                    List<RangeItem> list = findAll?.ListRanges;
                    int count = columns.Count;
                    int num = list?.Count ?? 0;
                    int width = ResultListView.ClientSize.Width;
                    int num2 = 0;
                    int num3 = 12;
                    for (int i = 0; i < count; i++)
                    {
                        ColumnHeader columnHeader = columns[i];
                        string text = columnHeader.Text;
                        int num4 = TextRenderer.MeasureText(graphics, text, SystemFonts.DefaultFont).Width + num3;
                        for (int j = startIndex; j <= endIndex; j++)
                        {
                            ListViewItem listViewItem = list[j].ListViewItem;
                            string text2 = listViewItem.SubItems[i].Text;
                            num4 = Math.Max(num4, TextRenderer.MeasureText(graphics, text2, SystemFonts.DefaultFont).Width + num3);
                        }
                        num2 += num4;
                        if (num > 0 && i == count - 1)
                        {
                            int num5 = width - num2;
                            if (num5 > 0)
                            {
                                num4 += num5;
                            }
                        }
                        columnHeader.Width = num4;
                    }
                }
            }
            finally
            {
                ResultListView.EndUpdate();
                ActiveView.ReleaseLock();
            }
        }

        private List<IRange> GetAllRanges(bool checkLocked)
        {
            bool flag = false;
            List<IRange> list = new List<IRange>();
            ActiveView.GetLock();
            try
            {
                switch (SelectedWithin)
                {
                    case Within.Sheet:
                        flag = AddRange(list, GetSelectedSheetRange(), checkLocked);
                        break;

                    case Within.Workbook:
                        flag = AddAllRanges(list, ActiveView.ActiveWorkbook, checkLocked);
                        break;

                    case Within.WorkbookSet:
                        flag = AddAllRanges(list, ActiveView.ActiveWorkbookSet, checkLocked);
                        break;
                }
            }
            finally
            {
                ActiveView.ReleaseLock();
            }
            if (!flag)
            {
                list.Clear();
            }
            return list;
        }

        private IRange GetEntireSheetRange()
        {
            if (ActiveView != null)
            {
                return ActiveView.ActiveWorksheet.Range;
            }
            return ActiveView.ActiveWorksheet.Cells;
        }

        private IRange GetSelectedSheetRange()
        {
            IRange range = ActiveView.RangeSelection;
            if (range.AreaCount == 1)
            {
                if (range.RowCount == 1 && range.ColumnCount == 1)
                {
                    range = GetEntireSheetRange();
                }
                else
                {
                    IRange mergeArea = range[0, 0].MergeArea;
                    if (mergeArea.Equals(range))
                    {
                        range = GetEntireSheetRange();
                    }
                }
            }
            return range;
        }

        private void SyncListRangeItems(bool forcedSyn)
        {
            int count = findAll.ListRanges.Count;
            if (VirtualListSize != count && !forcedSyn)
            {
                VirtualListSize = count;
            }
            else if (forcedSyn)
            {
                //强制刷新
                VirtualListSize = count;
            }
            if (VirtualListSize > 0)
                ResizeColumnHeader();
        }

        #endregion About Range

        #region About Find

        private void FindNext(bool breakAtEnd, bool showError)
        {
            ResetResultLabel();
            ActiveView.GetLock();
            IRange range = null;
            //bool activate = false;
            try
            {
                switch (SelectedWithin)
                {
                    case Within.Sheet:
                        IRange tcell = ActiveView.ActiveCell;
                        range = FindNext(GetSelectedSheetRange(), tcell);
                        if (range != null && !range.Equals(tcell))
                        {
                            switch (SelectedSearchOrder)
                            {
                                case SearchOrder.ByRows:
                                    if (range.Row >= tcell.Row)
                                    {
                                        break;
                                    }
                                    if (!breakAtEnd)
                                        break;
                                    range = null;
                                    break;

                                case SearchOrder.ByColumns:
                                    if (range.Column >= tcell.Column)
                                    {
                                        break;
                                    }
                                    if (!breakAtEnd)
                                        break;
                                    range = null;
                                    break;
                            }
                        }

                        //activate = true;
                        break;

                    case Within.Workbook:
                    case Within.WorkbookSet:
                        {
                            IRange entireSheetRange = GetEntireSheetRange();
                            IRange activeCell = ActiveView.ActiveCell;
                            range = FindNext(entireSheetRange, activeCell);
                            bool flag = true;
                            if (range != null && !range.Equals(activeCell))
                            {
                                switch (SelectedSearchOrder)
                                {
                                    case SearchOrder.ByRows:
                                        if (range.Row >= activeCell.Row)
                                        {
                                            flag = false;
                                        }
                                        break;

                                    case SearchOrder.ByColumns:
                                        if (range.Column >= activeCell.Column)
                                        {
                                            flag = false;
                                        }
                                        break;
                                }
                            }
                            if (flag)
                            {
                                if (SelectedWithin == Within.Workbook)
                                {
                                    //BreakAtEnd写死为false?
                                    range = FindNext(ActiveView.ActiveWorkbook, ActiveView.ActiveWorksheet, breakAtEnd);
                                }
                                else if (SelectedWithin == Within.WorkbookSet)
                                {
                                    SGForm.WorkbookView workbookview = ActiveView;
                                    IWorksheet workSheet = workbookview.ActiveWorksheet;
                                    IWorkbook workbook = (SelectedWithin == Within.Workbook) ? workSheet.Workbook : null;
                                    IWorksheet newSheet = null;
                                    range = FindNext(workSheet, workbook, true, out newSheet);
                                    if (range == null || (workSheet == newSheet && range.Equals(activeCell)))
                                    {
                                        range = FindNext(workbookview, workbook, breakAtEnd, out newSheet);
                                    }
                                    if (range != null && newSheet != null && newSheet != workSheet)
                                    {
                                        //Todo ??????????
                                    }
                                }
                                else
                                {
                                    range = FindNext(ActiveView.ActiveWorkbook, ActiveView.ActiveWorksheet, breakAtEnd);
                                    if (range == null || range.Equals(activeCell))
                                    {
                                        range = FindNext(ActiveView.ActiveWorkbookSet, ActiveView.ActiveWorkbook);
                                    }
                                }
                            }
                            break;
                        }
                }
                if (range != null)
                {
                    range.Worksheet.Select();
                    range.Activate();
                }
                else if (showError)
                {
                    MesBox.ErrorMessage("未发现匹配结果,或已达到搜索范围尽头");
                }
            }
            finally
            {
                ActiveView.ReleaseLock();
            }
        }

        private IRange FindNext(IRange searchRange, IRange afterRange)
        {
            if (afterRange != null && searchRange.AreaCount == 1 /*&& !Equals(searchRange, afterRange)*/)
            {
                //afterRange = null;
            }
            if (afterRange == null)
            {
                afterRange = GetAfterRange(searchRange);
            }
            IRange range = searchRange.Find(SearchText, afterRange,
                SelectedLookIn, SelectedLookAt,
                SelectedSearchOrder, SearchDirection.Next,
                SelectedCaseSensitive);

            return range;
        }

        private IRange FindNext(IWorkbook workbook, IWorksheet afterSheet, bool breakAtEnd)
        {
            IRange range = null;
            IWorksheets worksheets = workbook.Worksheets;
            IWorksheet worksheet = afterSheet;
            int num = afterSheet.Index;
            do
            {
                if (++num >= worksheets.Count)
                {
                    if (breakAtEnd)
                    {
                        break;
                    }
                    num = 0;
                }
                afterSheet = worksheets[num];
                if (afterSheet.Visible == SheetVisibility.Visible)
                {
                    range = FindNext(afterSheet.Cells, null);
                }
                if (range != null)
                {
                    break;
                }
            }
            while (afterSheet != worksheet);
            return range;
        }

        private IRange FindNext(IWorkbookSet workbookSet, IWorkbook afterBook)
        {
            IRange range = null;
            IWorkbooks workbooks = workbookSet.Workbooks;
            IWorkbook workbook = afterBook;
            int num = DesignerHelper.Commands.Edit.GetBookIndex(workbooks, afterBook);
            do
            {
                if (++num >= workbooks.Count)
                {
                    num = 0;
                }
                afterBook = workbooks[num];
                IWorksheets worksheets = afterBook.Worksheets;
                if (worksheets.Count > 0)
                {
                    IWorksheet afterSheet = worksheets[worksheets.Count - 1];
                    range = FindNext(afterBook, afterSheet, false);
                }
                if (range != null)
                    break;

            }
            while (afterBook != workbook);
            return range;
        }

        private IRange FindNext(IWorksheet afterSheet, IWorkbook workbook, bool breakAtEnd, out IWorksheet newActiveSheet)
        {
            //newActiveTab = null;
            //IRange range = null;
            //MainWindow643 @class = afterTab;
            //MainWindow644 class2 = @class.method_25();
            //int num = class2.method_16(afterTab);
            newActiveSheet = null;
            IRange range = null;
            IWorksheet sheet = afterSheet;
            IWorksheets sheets = afterSheet.Workbook.Worksheets;
            int num = sheet.Index;
            do
            {
                if (++num >= sheets.Count)
                {
                    if (breakAtEnd)
                        return range;
                    num = 0;
                }
                //if (++num >= class2.method_3())
                //{
                //    if (breakAtEnd)
                //    {
                //        return range;
                //    }
                //    num = 0;
                //}

                //afterTab = class2.method_7(num);
                //if (workbook == null || afterTab.method_22() == workbook)
                //{
                //    IRange range2 = afterTab.method_14();
                //    if (range2 != null)
                //    {
                //        range = this.FindNext(range2, null);
                //    }
                //}
                //if (range != null)
                //{
                //    break;
                //}
                afterSheet = sheets[num];
                if (workbook == null || afterSheet.Workbook == workbook)
                {
                    IRange range2 = afterSheet.Cells;
                    if (range2 != null)
                    {
                        range = FindNext(range2, null);
                    }
                }
                if (range != null)
                    break;
            }
            while (afterSheet != sheet);
            newActiveSheet = afterSheet;
            return range;
        }

        private IRange FindNext(SGForm.WorkbookView afterView, IWorkbook workbook, bool breakAtEnd, out IWorksheet newActiveSheet)
        {
            newActiveSheet = null;
            IRange range = null;

            SGForm.WorkbookView listNode = Mw.FileOperator.ViewList.Find(x => x.Equals(afterView));
            SGForm.WorkbookView listNode2 = listNode;
            int num = Mw.FileOperator.ViewList.IndexOf(afterView);
            do
            {
                if (++num >= Mw.FileOperator.ViewList.Count)
                {
                    /*↓是否开启对于所有打开文件(WorkbookSet)的循环查找*/
                    //if (breakAtEnd)
                    //    break;
                    num = 0;
                }
                listNode = Mw.FileOperator.ViewList[num];
                if (listNode == null)
                {
                    listNode = Mw.FileOperator.ViewList.First();
                }
                IWorksheets sheetsInternal = listNode.ActiveWorkbook.Worksheets;
                if (sheetsInternal.Count > 0)
                {
                    IWorksheet afterSheet = sheetsInternal[sheetsInternal.Count - 1];
                    //IWorksheet afterSheet = sheetsInternal[0];
                    range = FindNext(afterSheet, workbook, false, out newActiveSheet);
                }
                if (range != null)
                {
                    listNode.FindForm()?.Activate();
                    RefreshWbv();
                    break;
                }
            }
            while (listNode != listNode2);
            return range;
        }

        private void FinishFindAll()
        {
            ResetResultLabel();
            if (findAll.FirstFoundRange != null)
            {
                ActiveView.ActiveWorkbookSet.DoWork(() =>
                {
                    //this.GoTo(findAll.FirstFoundRange, false);
                    //highLightResults(findAll.RangeFound);
                });
            }
            else
            {
                VirtualListSize = 0;
                MesBox.ErrorMessage("未发现匹配结果");
            }
            SetResultLabel(GetResultText(findAll.ListRanges.Count, OperationType.Find));
            findAll.ClearAfterFind();

            AutoSizeListRangesOnCacheVirtualItems = true;
            SyncListRangeItems(false);
            ResultListView.Focus();
        }

        private void ToggleFindAll()
        {
            if (findAll != null)
            {
                findAll.Clear();
                findAll = null;
            }
            List<IRange> allranges = GetAllRanges(false);
            FindAll all = new FindAll(ActiveView);
            findAll = all;
            all.Init(SearchText, allranges,
                SelectedWithin,
                SelectedLookIn, SelectedLookAt,
                SelectedSearchOrder, SelectedCaseSensitive);
            findAll.Find();
            FinishFindAll();
        }

        private class FindAll
        {
            private List<RangeItem> _listRanges;
            //构造函数
            internal FindAll(SGForm.WorkbookView view)
            {
                View = view;
                //ListRanges = new List<RangeItem>();
                RangeFound = new List<IRange>();
            }

            internal IRange FirstFoundRange { get; private set; }

            internal List<RangeItem> ListRanges
            {
                get
                {
                    //ps 修改2.26 单元格定位
                    //List<RangeItem> t = new List<RangeItem>();
                    if (_listRanges != null)
                        return _listRanges;
                    View.ActiveWorkbookSet.DoWork(() =>
                    {
                        _listRanges = RangeFound.Select(range => new RangeItem(range.Worksheet, range.Row, range.Column)).ToList();
                    });
                    return _listRanges;
                }
            }

            private bool CaseSensitive { get; set; }
            private LookAt LookAt { get; set; }
            private FindLookIn LookIn { get; set; }
            private List<IRange> RangeFound { get; set; }
            private string ReplaceText { get; set; }
            private SearchOrder SearchOrder { get; set; }
            private List<IRange> SearchRanges { get; set; }
            private string SearchText { get; set; }
            private SGForm.WorkbookView View { get; set; }
            private Within Within { get; set; }

            internal void Clear()
            {
                ListRanges.Clear();
            }

            internal void ClearAfterFind()
            {
                FirstFoundRange = null;
                SearchRanges.Clear();
                SearchRanges = null;
            }

            internal void ClearListViewItems()
            {
                int count = ListRanges.Count;
                while (count-- > 0)
                {
                    ListRanges[count].ClearListViewItem();
                }
            }

            internal void Find()
            {
                if (SearchRanges.Count > 0)
                {
                    SearchRanges[0].WorkbookSet.GetLock();
                }
                try
                {
                    FirstFoundRange = null;
                    foreach (IRange range in SearchRanges)
                    {
                        IRange afterRange = GetAfterRange(range);
                        IRange range2 = Find(range, afterRange);
                        if (range2 != null && FirstFoundRange == null)
                        {
                            FirstFoundRange = range2;
                        }
                    }
                }
                finally
                {
                    if (SearchRanges.Count > 0)
                    {
                        SearchRanges[0].WorkbookSet.ReleaseLock();
                    }
                }
            }

            internal ListViewItem GetListViewItem(int index)
            {
                //return ListRanges.Count > index ? ListRanges[index].ListViewItem : null;
                IRange r = RangeFound[index];
                return new RangeItem(r.Worksheet, r.Row, r.Column).ListViewItem;//ps 修改2.26 单元格定位
            }

            internal IRange GetRange(int index)
            {
                if (ListRanges.Count > index)
                {
                    return ListRanges[index].Range;
                }
                return null;
            }

            //初始化
            internal void Init(string searchtext, List<IRange> searchRanges,
                Within selectedWithin,
                FindLookIn selectedLookIn, LookAt selectedLookAt,
                SearchOrder selectedSearch, bool selectedCaseSensitive)
            {
                SearchText = searchtext;
                SearchRanges = searchRanges;
                Within = selectedWithin;
                LookIn = selectedLookIn;
                LookAt = selectedLookAt;
                SearchOrder = selectedSearch;
                CaseSensitive = selectedCaseSensitive;
            }

            private IRange Find(IRange searchRange, IRange afterRange)
            {
                IRange range = null;
                IRange range2 = FindNext(searchRange, afterRange);
                if (range2 != null)
                {
                    range = range2;
                    do
                    {
                        RangeFound.Add(range2);
                        //ListRanges.Add(new RangeItem(range2.Worksheet, range2.Row, range2.Column));ps 修改2.26 单元格定位
                        range2 = FindNext(searchRange, range2);
                    }
                    while (!range2.Equals(range));
                }
                return range;
            }

            private IRange FindNext(IRange searchRange, IRange afterRange)
            {
                return searchRange.Find(SearchText, afterRange,
                    LookIn, LookAt, SearchOrder,
                    SearchDirection.Next, CaseSensitive);
            }
        }

        private class RangeItem
        {
            internal RangeItem(IWorksheet worksheet, int row, int col)
            {
                Worksheet = worksheet;
                Row = row;
                Column = col;
            }

            internal ListViewItem ListViewItem
            {
                get
                {
                    if (Item != null)
                        return Item;
                    IRange range = Range;
                    string[] items = new string[6];
                    items[0] = Worksheet.Workbook.Name;
                    items[1] = Worksheet.Name;
                    IName name = range.Name;
                    items[2] = name != null ? name.Name : "";
                    items[3] = range.Address;
                    string text = range.Text;
                    items[4] = (text ?? "");
                    items[5] = (range.HasFormula ? range.Formula : "");
                    Item = new ListViewItem(items);
                    Item.Tag = range;
                    return Item;
                }
            }

            internal IRange Range => Worksheet.Cells[Row, Column];
            private int Column { get; }
            private ListViewItem Item { get; set; }
            private int Row { get; }
            private IWorksheet Worksheet { get; }

            internal void ClearListViewItem()
            {
                Item = null;
            }
        }

        #endregion About Find

        #region About replace

        private void Replace()
        {
            if (RefreshSuccessed())
            {
                List<IRange> range = new List<IRange>();
                int count = 0;
                try
                {
                    ActiveView.GetLock();
                    AddRange(range, ActiveView.ActiveCell, true);
                    if (range.Count <= 0)
                    {
                        MesBox.ErrorMessage("无法进行该操作,请检查单元格是否被锁定");
                        return;
                    }
                    for (int i = 0; i < range.Count; i++)
                    {
                        count += range[i].Replace(SearchText, ReplaceText, SelectedLookAt, SelectedSearchOrder, SelectedCaseSensitive);
                    }
                    FindNext(false, false);
                }
                finally
                {
                    ActiveView.ReleaseLock();
                }
            }
            else
            {
                MesBox.ErrorMessage("没有文件打开,操作无法进行");
            }
        }

        private void ReplaceAll()
        {
            if (RefreshSuccessed())
            {
                int count = 0;
                ActiveView.GetLock();
                try
                {
                    List<IRange> replaceRange = GetAllRanges(true);
                    if (replaceRange.Count > 0)
                    {
                        for (int i = 0; i < replaceRange.Count; i++)
                        {
                            count += replaceRange[i].Replace(SearchText, ReplaceText, SelectedLookAt, SelectedSearchOrder, SelectedCaseSensitive);
                        }
                        if (count > 0)
                            SetResultLabel(GetResultText(count, OperationType.Replace));
                        else
                            SetResultLabel("未发现匹配的查找项,请检查关键词");
                    }
                    else
                        MesBox.ErrorMessage("无法进行该操作,请检查单元格是否被锁定");
                }
                catch (Exception ex)
                {
                    MesBox.ErrorMessage(ex);
                }
                finally
                {
                    ActiveView.ReleaseLock();
                }
            }
            else
                MesBox.ErrorMessage("无法进行该操作(Null WBV)");
        }

        #endregion About replace

        #region HandleFormEvents

        private void backgroundFindAll_DoWork(object sender, DoWorkEventArgs e)
        {
            //FindAll argument = (FindAll)e.Argument;
            //argument.Find();
            //e.Result = argument;
        }

        private void backgroundFindAll_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
        }

        private void backgroundFindAll_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
        }

        private void buttonClose_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void buttonFindAll_Click(object sender, EventArgs e)
        {
            ResetResultLabel();
            if (RefreshSuccessed())
            {
                ToggleFindAll();
            }
        }

        private void buttonFindNext_Click(object sender, EventArgs e)
        {
            if (RefreshSuccessed())
            {
                FindNext(Loopthrough, true);
            }
        }

        private void buttonReplace_Click(object sender, EventArgs e)
        {
            Replace();
        }

        private void buttonReplaceAll_Click(object sender, EventArgs e)
        {
            ReplaceAll();
        }

        private void checkBoxChangeOpacity_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxChangeOpacity.Checked)
            {
                trackBarChangeOpactiy.Enabled = true;
                radioOpaAlways.Enabled = true;
                radioOpaLostFocus.Enabled = true;
            }
            else
            {
                trackBarChangeOpactiy.Enabled = false;
                radioOpaAlways.Enabled = false;
                radioOpaLostFocus.Enabled = false;
            }
            SetFormOpacity(true);
        }

        private void comboBoxWithin_SelectionChangeCommitted(object sender, EventArgs e)
        {
            //if (SelectedWithin == Within.WorkbookSet)//ps 取消了循环查找的可选功能
            //{
            //    checkBoxLoopThrough.Enabled = false;
            //    checkBoxLoopThrough.CheckState = CheckState.Checked;
            //}
            //else
            //    checkBoxLoopThrough.Enabled = true;
        }

        private void FindReplaceDialog_FormClosed(object sender, FormClosedEventArgs e)
        {
            _frd = null;
            RemoveEventHandler();
            trackBarChangeOpactiy.Enabled = false;
        }

        private void FindReplaceDialog_Load(object sender, EventArgs e)
        {
            comboBoxLookIn.SelectedIndex = 0;
            comboBoxSearch.SelectedIndex = 0;
            comboBoxWithin.SelectedIndex = 0;
            trackBarChangeOpactiy.Enabled = true;
        }

        private void ResultListView_CacheVirtualItems(object sender, CacheVirtualItemsEventArgs e)
        {
            if (AutoSizeListRangesOnCacheVirtualItems)
            {
                AutoSizeListRangesOnCacheVirtualItems = false;
                AutoSizeRangeList(e.StartIndex, e.EndIndex);
            }
        }

        private void ResultListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            IRange range = e.Item.Tag as IRange;
            if (range == null)
                return;
            IBookForm wbf =
                Mw.FileOperator.AllFormsList.FirstOrDefault(x => x.ActiveBook == (range.Worksheet.Workbook));
            wbf?.GetForm().Activate();
            ActiveView.ActiveWorkbookSet.DoWork(() =>
            {
                range.Worksheet.Select();
                range.Select();
            });
        }

        private void ResultListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
        {
            ListViewItem cacheTempItem = new ListViewItem();
            ActiveView.GetLock();
            try
            {
                ListViewItem listViewItem = findAll.GetListViewItem(e.ItemIndex);
                e.Item = listViewItem ?? cacheTempItem;
            }
            finally
            {
                ActiveView.ReleaseLock();
            }
        }

        private void trackBarChangeOpactiy_Scroll(object sender, EventArgs e)
        {
            SetFormOpacity(true);
        }

        #endregion HandleFormEvents

        private void CancelHighLight(List<IRange> rangelist)
        {
            if (rangelist.Count == 0) return;
            foreach (IRange t in rangelist.Where(t => t != null))
            {
                t.Interior.Color = Colors.IndianRed;
                t.Interior.ColorIndex = Colors.IndianRed.ToArgb();
            }
        }

        private void CheckTabPageControl()
        {
            if (tabControl1.SelectedTab == tabPageFind)
            {
                if (!tabPageReplace.Controls.Contains(panel1))
                    return;
                tabPageReplace.Controls.Remove(panel1);
                tabPageFind.Controls.Add(panel1);

                buttonReplace.Visible = false;
                buttonReplaceAll.Visible = false;//enable不应在此处改变

                labelReplace.Visible = false;
                comboBoxReplace.Visible = false;
                //comboBoxReplace.Enabled = false;
            }
            else if (tabControl1.SelectedTab == tabPageReplace)
            {
                if (!tabPageFind.Controls.Contains(panel1))
                    return;
                tabPageFind.Controls.Remove(panel1);
                tabPageReplace.Controls.Add(panel1);

                buttonReplace.Visible = true;
                buttonReplaceAll.Visible = true;

                labelReplace.Visible = true;
                comboBoxReplace.Visible = true;
                //comboBoxReplace.Enabled = true;
            }
        }

        private void comboBoxWithin_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void FindReplaceDialog_Activated(object sender, EventArgs e)
        {
            if (trackBarChangeOpactiy.Enabled)
            {
                SetFormOpacity(true);
            }
        }

        private void FindReplaceDialog_Deactivate(object sender, EventArgs e)
        {
            if (trackBarChangeOpactiy.Enabled)
            {
                SetFormOpacity(false);
            }
        }

        private void FindReplaceDialog_Resize(object sender, EventArgs e)
        {
            //ResizeColumnHeader();
        }

        private void HighLightResults(List<IRange> rangelist)
        {
            if (rangelist.Count <= 0) return;
            foreach (IRange range in rangelist.Where(range => range != null))
            {
                range.Interior.Color = SpreadsheetGear.Color.FromArgb(255, 255, 0);
            }
        }

        private void radioOpaAlways_CheckedChanged(object sender, EventArgs e)
        {
            SetFormOpacity(true);
        }

        private void ResizeColumnHeader()
        {
            viewAddress.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
            viewBook.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
            viewName.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
            viewSheet.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
            viewValue.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);

            int w = ResultListView.Width - viewAddress.Width - viewBook.Width - viewName.Width -
                    viewSheet.Width - viewValue.Width - 25;
            //viewValue.Width = w / 2;
            viewFormulas.Width = w;
        }

        private void tabControl1_Selected(object sender, TabControlEventArgs e)
        {
            CheckTabPageControl();
        }
    }
}